/**
 * @fileOverview anchor controller
 * @author huangtonger@aliyun.com
 */

const Base = require('../../../simpleBase');
const Global = require('../global');
const Util = require('../util/');

class Controller extends Base {
  getDefaultCfg() {
    return {
      _anchorItemCache: {}
    };
  }
  init() {
    const graph = this.graph;
    graph.on('afteritemdraw', ev => {
      ev.item.isAnchorShow && this.showAnchor(ev.item);
    });
    graph.on('beforeitemdestroy', ev => {
      this._clearAnchor(ev.item);
    });
    graph.on('afteritemhide', ev => {
      if (ev.item.isNode) {
        this._clearAnchor(ev.item);
      }
    });
  }
  _updateAnchor(item) {
    const graph = this.graph;
    item.anchorShapes.forEach(anchor => {
      anchor.updatePosition();
    });
    graph.draw();
  }
  _drawAnchor(item, group, indexs, bool) {
    const anchorPoints = item.getAnchorPoints();
    this._clearAnchor(item);
    Util.each(anchorPoints, (point, index) => {
      if (indexs && indexs.indexOf(index) === -1) {
        return;
      }
      let hotspot;

      const shape = group.addShape('marker', {
        attrs: {
          symbol: 'circle',
          ...Global.anchorPointStyle,
          x: point.x,
          y: point.y
        },
        freezePoint: point,
        item,
        index,
        eventPreFix: 'anchor',
        isItemChange() {
          return;
        },
        zIndex: Global.zIndex.anchorPoint
      });
      shape.toFront();
      shape.eventPreFix = 'anchor';
      shape.showHotspot = () => {
        hotspot = group.addShape('marker', {
          attrs: {
            symbol: 'circle',
            ...Global.anchorHotsoptStyle,
            x: point.x,
            y: point.y
          },
          freezePoint: point,
          capture: false,
          zIndex: Global.zIndex.anchorHotsopt
        });
        item.anchorShapes.push(hotspot);
        shape.hasHotspot = true;
        hotspot.toFront();
        shape.toFront();
      };
      shape.getIndex = () => {
        return index;
      };
      shape.getItem = () => {
        return item;
      };
      shape.getPoint = () => {
        return point;
      };
      shape.updatePosition = () => {
        const anchorPoints = item.getAnchorPoints();
        const point = anchorPoints[index];
        shape.attr(point);
      };
      shape.setActived = () => {
        shape.attr(Global.anchorPointHoverStyle);
      };
      shape.clearActived = () => {
        shape.attr(Global.anchorPointStyle);
      };
      shape.isAnchor = true;
      shape.setHotspotActived = bool => {
        if (hotspot) {
          if (bool) {
            hotspot.attr(Global.anchorHotsoptActivedStyle);
          } else {
            hotspot.attr(Global.anchorHotsoptStyle);
          }
        }
      };
      if (bool) {
        shape.showHotspot();
      }
      item.anchorShapes.push(shape);
      item.getAllAnchors = () => {
        return item.anchorShapes.filter(shape => {
          return shape.isAnchor;
        });
      };
      item.getAnchor = index => {
        return item.anchorShapes.find(shape => {
          return shape.get('index') === index;
        });
      };
    });
  }
  _clearAnchor(item) {
    if (item.anchorShapes) {
      item.anchorShapes.forEach(shape => {
        shape.remove();
      });
    }
    item.anchorShapes = [];
  }
  setHotspotActived(anchor, bool) {
    const diagram = this.diagram;
    const graph = diagram.getGraph();
    anchor.setHotspotActived(bool);
    graph.draw();
  }
  showAnchor(item, indexs, isShowHotspot) {
    if (!item.isVisible()) {
      return;
    }
    const graph = this.graph;
    const anchorItemCache = this._anchorItemCache;
    const rootGroup = graph.getRootGroup();
    this._drawAnchor(item, rootGroup, indexs, isShowHotspot);
    item.isAnchorShow = true;
    anchorItemCache[item.id] = item;
  }
  clearAnchor(param) {
    const graph = this.graph;
    const itemCache = graph.get('itemCache');
    const anchorItemCache = this._anchorItemCache;
    let items = param;
    if (Util.isObject(param)) {
      items = [ param ];
    } else if (Util.isString(param)) {
      items = [ itemCache[param] ];
    } else {
      items = anchorItemCache;
    }
    Util.each(items, item => {
      this._clearAnchor(item);
      item.isAnchorShow = false;
      delete anchorItemCache[item.id];
    });
    graph.draw();
  }
}

module.exports = Controller;
